package com.hzlh.configuration.cas;

import lombok.extern.slf4j.Slf4j;
import org.jasig.cas.client.authentication.AuthenticationFilter;
import org.jasig.cas.client.session.SessionMappingStorage;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.jasig.cas.client.util.AssertionThreadLocalFilter;
import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
import org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.session.SessionRepository;

/**
 * 单点登录
 */
@Slf4j
@Configuration("ssoWebConfiguration")
public class SSOWebConfiguration {

    @Autowired
    public StringRedisTemplate redisTemplate;

    @Autowired
    private SessionRepository sessionRepository;


    @Bean
    public CasClientProperties clientProperties(){
        return new CasClientProperties();
    }

    @Bean
    public SingleSignOutFilter getSingleSignOutFilter(){

        return new SingleSignOutFilter();
    }

    /**
     * 新增<code>SessionMappingStorage</code>实现类
     *
     * 采用redis存储session
     * @return
     */
    @Bean
    public SessionMappingStorage sessionMappingStorage(){
        return new RedisSessionMappingStorage(redisTemplate, sessionRepository);
    }

    /**
     * 单点登出过滤器，需位置排在其他几个前面
     * @return
     */
    @Bean
    public FilterRegistrationBean singleSignOutFilter(){
        LOGGER.info("FilterRegistrationBean--cas单点登出过滤器");
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(getSingleSignOutFilter());
        registration.setName("CAS Single Sign Out Filter");
        registration.setOrder(1);
        registration.addUrlPatterns("/*");
        registration.addInitParameter("casServerUrlPrefix", clientProperties().getCasServerPrefix() + "/logout");
        registration.addInitParameter("serverName", clientProperties().getCasServerPrefix());

        getSingleSignOutFilter().setSessionMappingStorage(sessionMappingStorage());
        LOGGER.info("FilterRegistrationBean--cas单点登出过滤器，.getCasServerPrefix:" + clientProperties().getCasServerPrefix() );
        return registration;
    }

    /**
     * 认证过滤器
     * @return
     */
    @Bean
    public FilterRegistrationBean authenticationFilter(){
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new AuthenticationFilter());
        registration.setName("CAS Authentication Filter");
        registration.setOrder(2);
        registration.addUrlPatterns("/user/login");
        registration.addInitParameter("casServerLoginUrl", clientProperties().getCasServerPrefix() + "/login");
        registration.addInitParameter("serverName", clientProperties().getClientHost());
        registration.addInitParameter("gateway", "false");

        return registration;
    }

    /**
     * cas3.0 协议接收票据认证实现
     * @return
     */
    @Bean
    public FilterRegistrationBean cas20ProxyReceivingTicketValidationFilter(){
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new Cas20ProxyReceivingTicketValidationFilter());
        registration.setName("CAS Validation Filter");
        registration.setOrder(3);
        registration.addUrlPatterns("/*");
        registration.addInitParameter("casServerUrlPrefix", clientProperties().getCasServerPrefix());
        registration.addInitParameter("acceptAnyProxy", "true");
        registration.addInitParameter("serverName", clientProperties().getClientHost());
        registration.addInitParameter("redirectAfterValidation", "true");
        registration.addInitParameter("useSession", "true");
        registration.addInitParameter("encoding", "utf-8");

        return registration;
    }

    /**
     * HttpServletReques包装过滤器
     * @return
     */
    @Bean
    public FilterRegistrationBean httpServletRequestWrapperFilter(){
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new HttpServletRequestWrapperFilter());
        registration.setName("CAS HttpServletRequest Wrapper Filter");
        registration.setOrder(4);
        registration.addUrlPatterns("/*");

        return registration;
    }

    /**
     * 本地线程断言
     * @return
     */
    @Bean
    public FilterRegistrationBean assertionThreadLocalFilter(){
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new AssertionThreadLocalFilter());
        registration.setName("CAS Assertion Thread Local Filter");
        registration.setOrder(5);
        registration.addUrlPatterns("/*");
        return registration;
    }

    /**
     * 单点登出session监听器，根据ST删除session
     * @return
     */
    @Bean
    public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(){
        LOGGER.info("singleSignOutHttpSessionListener--cas单点登出,根据ST删除session");
        return new SingleSignOutHttpSessionListener();
    }
}
